嗨,我是Hogan
目前在經營自己的自媒體 hogan.tech
主要分享一些有關於程式碼、軟體和科技業經驗分享
有興趣的讀者可以進一步關注我,進而獲得更多資訊唷!
未來文章一併更新於此網站 Hogan.B Lab
並且包含多語系 繁體中文、英文、日文、簡體中文
觀看分類:React 白話文運動、其他系列
如果想要快速查找其他文章請點選目錄
成立 hogan.tech 的初衷是
希望每個正在這條路上探索的人,
都可以透過 Hogan.tech 嘗試進入程式領域。
前一篇介紹新的hook,useRef
這一篇則是會介紹另一個hook,useContext
不過在介紹 useContext 之前,則是會介紹元件樹的狀態管理
這邊我使用之前的 StarRating 元件來實作,狀態由父元件傳至子元件的狀態管理
基本上都是透過元件的參數傳遞由上傳遞至下
const colorData = [
{ id: "1", title: "red", color: "red", rating: 5 },
{ id: "2", title: "blue", color: "blue", rating: 2 },
{ id: "3", title: "green", color: "green", rating: 4 },
]
export default function App() {
const [colors] = useState(colorData)
return <ColorList colors={colors}></ColorList>
}
這邊先訂一組 Json 資料,並且在父元件使用 useState 去做狀態的宣告
也將此資料傳入 ColorList 元件
export default function ColorList({ colors = [] }) {
if (!colors.length) return <div>No colors</div>;
return (
<div>
{colors.map(color => <Color key={color.id} {...color} />)}
</div>
)
}
透過傳入的 colorData 先判斷陣列是否有資料,沒有資料的話顯示 No colors
否則根據這些資料,再次傳入 Color 子元件
export default function Color({ title, color, rating }) {
return (
<section>
<h1>{title}</h1>
<div style={{ height: 50, width: 50, backgroundColor: color }}></div>
<StarRating selectedStars={rating} />
</section>
)
}
透過 ColorList 父元件傳入的資料,分別有 title、color 、rating
分別顯示在不同的位子,其中也在 div 區塊,使用css style 顯示顏色
也透過 rating 傳入到最後的 StarRating 顯示星星數
const Star = ({ selected = true, onSelect = f => f }) => (
<FaStar color={selected ? 'red' : 'gray'} onCLick={onSelect}></FaStar>
)
const createArray = length => [...Array(length)];
export default function StarRating({ totalStars = 5, selectedStars = 0 }) {
return <div>
{createArray(totalStars).map((n, i) =>
<Star
key={i}
selected={selectedStars > i}
/>
)}
<p>
{selectedStars} of {totalStars} stars
</p>
</div>
}
由 props 可以做到父元件到子元件的參數傳遞,但如果我們希望子元件按下刪除按鈕,就可以刪除元件呢?
我們就需要再透過傳遞函數的方式,在子元件一一回傳,並且使用 useState 中的 setState 來去操作
export default function Color({ id, title, color, rating, onRemove = f => f }) {
return (
<section>
<h1>{title}</h1>
<button onClick={() => onRemove(id)}>
<FaTrash />
</button>
<div style={{ height: 50, width: 50, backgroundColor: color }}></div>
<StarRating selectedStars={rating} />
</section >
)
}
先在 Color 元件新增一個callback function 叫做 onRemove
只要點擊此按鈕,就會觸發一次 onRemove
export default function ColorList({ colors = [], onRemoveColor = f => f }) {
if (!colors.length) return <div>No colors</div>;
return (
<div style={{ padding: 100 }}>
{colors.map(color => <Color key={color.id} {...color} onRemove={onRemoveColor} />)}
</div>
)
}
再到上一層的父原件,一樣新增一個 callback function 叫做 onRemoveColor,並且將此函數往下傳遞
export default function App() {
const [colors, setColors] = useState(colorData)
return <ColorList colors={colors} onRemoveColor={
id => {
const newColors = colors.filter(color => color.id !== id);
setColors(newColors)
}
} ></ColorList>
}
最後在最上層的父原件,定義好 onRemoveColor 需要做哪些事情
這邊做了兩件事情,透過子元件回傳的 id,將陣列過濾
最後在使用 setColors 將狀態更新
講完了狀態由上至下以及由下至上,應該不難發現,如果今天我們的元件很多層
我們就必須要在有經過的元件,一直將參數做傳遞,這是一件非常麻煩且冗長的事情
React 因此也有了另一種狀態管理,稱為Context
可以想像成,我們把每一層元件全部包起來,只要在裡面任何元件有使用到的地方,只要在該元件做使用就好,不需要再一層一層的傳遞
如果要用日常生活來比喻的話
由上至下、由下至上就像是火車,如果要從一個火車站傳遞貨物到終點站,需要一站一站的經過
Context 則是像飛機,如果要從一個機場傳遞貨物到終點站,則可以直接傳送資料到該目的地
接續會深入講解 Context 的寫法以及 Context Provider 的用法
這一篇比較了幾種不同的 React 狀態管理,由上而下、由下而上、Context
下一篇就會深入講解Context 的概念與實作
如果有任何建議與疑問也歡迎留言!
如果喜歡此系列文章,請不吝於按下喜歡及分享,讓更多人看到唷~